home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / varie / uae-0_64.lha / uae-0.6.4 / src / xwin.c < prev    next >
C/C++ Source or Header  |  1996-09-10  |  25KB  |  954 lines

  1.  /* 
  2.   * UAE - The Un*x Amiga Emulator
  3.   * 
  4.   * X interface
  5.   * 
  6.   * Copyright 1995, 1996 Bernd Schmidt
  7.   * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
  8.   */
  9.  
  10. #include "sysconfig.h"
  11. #include "sysdeps.h"
  12.  
  13. #include <X11/Xlib.h>
  14. #include <X11/Xutil.h>
  15. #include <X11/keysym.h>
  16. #include <X11/cursorfont.h>
  17.  
  18. #ifndef DONT_WANT_SHM
  19. #include <sys/ipc.h>
  20. #include <sys/shm.h>
  21. #include <X11/extensions/XShm.h>
  22. #endif
  23.  
  24. #include <ctype.h>
  25. #include <signal.h>
  26.  
  27. #include "config.h"
  28. #include "options.h"
  29. #include "memory.h"
  30. #include "custom.h"
  31. #include "newcpu.h"
  32. #include "xwin.h"
  33. #include "keyboard.h"
  34. #include "keybuf.h"
  35. #include "gui.h"
  36. #include "debug.h"
  37.  
  38. #ifdef __cplusplus
  39. static RETSIGTYPE sigbrkhandler(...)
  40. #else
  41. static RETSIGTYPE sigbrkhandler(int foo)
  42. #endif
  43. {
  44.     activate_debugger();
  45.  
  46. #if !defined(__unix) || defined(__NeXT__)
  47.     signal(SIGINT, sigbrkhandler);
  48. #endif
  49. }
  50.  
  51. void setup_brkhandler(void)
  52. {
  53. #if defined(__unix) && !defined(__NeXT__)
  54.     struct sigaction sa;
  55.     sa.sa_handler = sigbrkhandler;
  56.     sa.sa_flags = 0;
  57. #ifdef SA_RESTART
  58.     sa.sa_flags = SA_RESTART;
  59. #endif
  60.     sigemptyset(&sa.sa_mask);
  61.     sigaction(SIGINT, &sa, NULL);
  62. #else
  63.     signal(SIGINT, sigbrkhandler);
  64. #endif    
  65. }
  66.  
  67. static Display *display;
  68. static int screen;
  69. static Window rootwin, mywin;
  70.  
  71. static GC whitegc,blackgc;
  72. static XColor black,white;
  73. static Colormap cmap;
  74.  
  75. static int need_dither;
  76.  
  77. static int autorepeatoff = 0;
  78. static char *image_mem;
  79. static XImage *img;
  80. static Visual *vis;
  81. static XVisualInfo visualInfo;
  82. static int bitdepth, bit_unit;
  83. #ifndef DONT_WANT_SHM
  84. static int use_shm = 1;
  85. static XShmSegmentInfo shminfo;
  86. #endif
  87. static Cursor blankCursor, xhairCursor;
  88. static int cursorOn;
  89.  
  90. #ifdef LOW_BANDWIDTH
  91. static int use_low_bandwidth = 1;
  92. #else
  93. static int use_low_bandwidth = 0;
  94. #endif
  95.  
  96. xcolnr xcolors[4096];
  97.  
  98.  /* Keyboard and mouse */
  99.  
  100. static int keystate[256];
  101.  
  102. int buttonstate[3];
  103. int lastmx, lastmy;
  104. int newmousecounters;
  105.  
  106. static int inwindow;
  107. const long int eventmask = (KeyPressMask|KeyReleaseMask|ButtonPressMask
  108.                 |ButtonReleaseMask|PointerMotionMask
  109.                 |FocusChangeMask|EnterWindowMask
  110.                 |ExposureMask
  111.                 |LeaveWindowMask);
  112.  
  113. static int vsize, hsize, hpixels;
  114. static char *oldpixbuf;
  115.  
  116. struct vidbuf_description gfxvidinfo;
  117.  
  118. void flush_line(int y)
  119. {
  120.     int xs = 0, xe;
  121.     int len, factor;
  122.     char *linebuf = y*gfxvidinfo.rowbytes + gfxvidinfo.bufmem;
  123.     char *src, *dst;
  124.     if (gfxvidinfo.maxlinetoscr)
  125.     xe = gfxvidinfo.maxlinetoscr-1;
  126.     else
  127.     xe = hsize-1;
  128.  
  129.     if (!use_low_bandwidth)
  130.     fprintf(stderr, "Bug!\n");
  131.     
  132.     switch(gfxvidinfo.pixbytes) {
  133.      case 4:
  134.     {
  135.         int *newp = (int *)linebuf;
  136.         int *oldp = (int *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  137.         while (newp[xs] == oldp[xs]) {
  138.         if (xs == xe)
  139.             return;
  140.         xs++;
  141.         }
  142.         while (newp[xe] == oldp[xe]) xe--;
  143.         
  144.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  145.     }
  146.     break;
  147.      case 2:
  148.     {
  149.         short *newp = (short *)linebuf;
  150.         short *oldp = (short *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  151.         while (newp[xs] == oldp[xs]) {
  152.         if (xs == xe)
  153.             return;
  154.         xs++;
  155.         }
  156.         while (newp[xe] == oldp[xe]) xe--;
  157.  
  158.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  159.     }
  160.     break;
  161.      case 1:
  162.     {
  163.         char *newp = (char *)linebuf;
  164.         char *oldp = (char *)(oldpixbuf + y*gfxvidinfo.rowbytes);
  165.         while (newp[xs] == oldp[xs]) {
  166.         if (xs == xe)
  167.             return;
  168.         xs++;
  169.         }
  170.         while (newp[xe] == oldp[xe]) xe--;
  171.  
  172.         dst = (char *)(oldp + xs); src = (char *)(newp + xs);
  173.     }
  174.     break;
  175.  
  176.      default:
  177.     abort();
  178.     break;
  179.     }
  180.  
  181.     len = xe - xs + 1;
  182.     memcpy (dst, src, len * gfxvidinfo.pixbytes);
  183.     
  184.     if (need_dither) {
  185.     UBYTE *target = (UBYTE *)image_mem + img->bytes_per_line * y;
  186.     xs &= ~(8/bit_unit - 1);
  187.     len = xe - xs + 1;
  188.     len += 3; len &= ~3;
  189.     len += (8/bit_unit - 1); len &= ~(8/bit_unit-1);
  190.     if (len & 3)
  191.         printf("%d\n",len);
  192.     DitherLine(target + xs*bit_unit/8, (UWORD *)linebuf + xs, xs, y, len, bit_unit);
  193.     }
  194. #ifndef DONT_WANT_SHM
  195.     if (use_shm)
  196.     XShmPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1, 0);
  197.     else
  198. #endif
  199.     XPutImage(display, mywin, blackgc, img, xs, y, xs, y, len, 1);
  200. }
  201.  
  202. void flush_block (int ystart, int ystop)
  203. {
  204.     int len, xs = 0;
  205.     
  206.     if (gfxvidinfo.maxlinetoscr)
  207.     len = gfxvidinfo.maxlinetoscr;
  208.     else
  209.     len = hsize;
  210. #ifndef DONT_WANT_SHM
  211.     if (use_shm)
  212.     XShmPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len,
  213.              ystop - ystart + 1, 0);
  214.     else
  215. #endif
  216.     XPutImage(display, mywin, blackgc, img, xs, ystart, 0, ystart, len, 
  217.           ystop - ystart + 1);
  218. }
  219.  
  220. void flush_screen (int ystart, int ystop)
  221. {
  222. #ifndef DONT_WANT_SHM
  223.     if (use_shm) XSync(display, 0);
  224. #endif
  225. }
  226.  
  227. void calc_adjustment(void)
  228. {
  229.     switch (screen_res) {
  230.      case 0: case 1: case 2: /* LoRes, 320x300 */
  231.     gfxvidinfo.x_adjust = prev_max_diwstop - 320;
  232.     break;
  233.     
  234.      case 3: /* 640x480 */
  235.     gfxvidinfo.x_adjust = prev_max_diwstop - 640;
  236.     break;
  237.      default:
  238.     gfxvidinfo.x_adjust = 0;
  239.     break;
  240.     }
  241. }
  242.  
  243. static __inline__ int bitsInMask(unsigned long mask)
  244. {
  245.     /* count bits in mask */
  246.     int n = 0;
  247.     while(mask) {
  248.     n += mask&1;
  249.     mask >>= 1;
  250.     }
  251.     return n;
  252. }
  253.  
  254. static __inline__ int maskShift(unsigned long mask)
  255. {
  256.     /* determine how far mask is shifted */
  257.     int n = 0;
  258.     while(!(mask&1)) {
  259.     n++;
  260.     mask >>= 1;
  261.     }
  262.     return n;
  263. }
  264.  
  265. static int get_color(int r, int g, int b, xcolnr *cnp)
  266. {
  267.     XColor col;
  268.     char str[10];
  269.     sprintf(str, "rgb:%x/%x/%x", r, g, b);
  270.     XParseColor(display, cmap, str, &col);
  271.     if (XAllocColor(display, cmap, &col)) {
  272.     *cnp = col.pixel;
  273.     return 1;
  274.     }
  275.     return 0;
  276. }
  277.  
  278. static int init_colors(void)
  279. {
  280.     if (need_dither) {
  281.     if (bitdepth == 1)
  282.         setup_greydither (1, get_color);
  283.     else
  284.         setup_dither (bitdepth, get_color);
  285.     return 1;
  286.     }
  287.     
  288.     if (bitdepth != 8 && bitdepth != 12 
  289.     && bitdepth != 16 && bitdepth != 24) {
  290.         fprintf(stderr, "Unsupported bit depth (%d)\n", bitdepth);
  291.     return 0;
  292.     }
  293.     
  294. #ifdef __cplusplus
  295.     switch(visualInfo.c_class) 
  296. #else
  297.     switch(visualInfo.class) 
  298. #endif
  299.     {
  300.      case TrueColor: 
  301.     {        
  302.         int red_bits = bitsInMask(visualInfo.red_mask);
  303.         int green_bits = bitsInMask(visualInfo.green_mask);
  304.         int blue_bits = bitsInMask(visualInfo.blue_mask);
  305.         int red_shift = maskShift(visualInfo.red_mask);
  306.         int green_shift = maskShift(visualInfo.green_mask);
  307.         int blue_shift = maskShift(visualInfo.blue_mask);
  308.         alloc_colors64k(red_bits, green_bits, blue_bits, red_shift, 
  309.                 green_shift, blue_shift);
  310.     }
  311.     break;
  312.  
  313.      case GrayScale:
  314.      case PseudoColor:
  315.     alloc_colors256(get_color);
  316.     break;
  317.     
  318.      default:
  319. #ifdef __cplusplus
  320.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.c_class);
  321. #else
  322.     fprintf(stderr, "Unsupported visual class (%d)\n", visualInfo.class);
  323. #endif
  324.     return 0;
  325.     }
  326.     return 1;
  327. }
  328.  
  329. int graphics_init(void)
  330. {
  331.     int i,j;
  332.     char *display_name = 0;
  333.     XSetWindowAttributes wattr;
  334.     XPixmapFormatValues *xpfvs;
  335.     need_dither = 0;
  336.     
  337.     if (screen_res < 3) {
  338.     fprintf(stderr, "Low resolution mode selected. Forcing 320x300.\n");
  339.     }
  340.     
  341.     display = XOpenDisplay(display_name);
  342.     if (display == 0)  {
  343.     fprintf(stderr, "Can't connect to X server %s\n", XDisplayName(display_name));
  344.     return 0;
  345.     }
  346.     screen = XDefaultScreen(display);
  347.     rootwin = XRootWindow(display,screen);
  348.     
  349.     /* try for a 12 bit visual first, then a 16 bit, then a 24 bit, then 8 bit */
  350.     if (XMatchVisualInfo(display, screen, 12, TrueColor, &visualInfo)) {
  351.     } else if (XMatchVisualInfo(display, screen, 16, TrueColor, &visualInfo)) {
  352.     } else if (XMatchVisualInfo(display, screen, 24, TrueColor, &visualInfo)) {
  353.     } else if (XMatchVisualInfo(display, screen, 8, PseudoColor, &visualInfo)) {
  354.     /* for our HP boxes */
  355.     } else if (XMatchVisualInfo(display, screen, 8, GrayScale, &visualInfo)) {
  356.     } else if (XMatchVisualInfo(display, screen, 4, PseudoColor, &visualInfo)) {
  357.     /* VGA16 server. Argh. */
  358.     } else if (XMatchVisualInfo(display, screen, 1, StaticGray, &visualInfo)) {
  359.     /* Mono server. Yuk */
  360.     } else {
  361.     fprintf(stderr, "Can't obtain appropriate X visual.\n");
  362.     return 0;
  363.     }
  364.     vis = visualInfo.visual;
  365.     bitdepth = visualInfo.depth;
  366.     
  367.     /* We now have the bitdepth of the display, but that doesn't tell us yet
  368.      * how many bits to use per pixel. The VGA16 server has a bitdepth of 4,
  369.      * but uses 1 byte per pixel. */
  370.     xpfvs = XListPixmapFormats(display, &i);
  371.     for (j = 0; j < i && xpfvs->depth != bitdepth; j++, xpfvs++)
  372.     ;
  373.     if (j == i) {
  374.     fprintf(stderr, "Your X server is feeling ill.\n");
  375.     return 0;
  376.     }
  377.     
  378.     bit_unit = xpfvs->bits_per_pixel;
  379.     fprintf(stderr, "Using %d bit visual, %d bits per pixel\n", bitdepth, bit_unit);
  380.  
  381.     switch (screen_res) {
  382.      case 0: case 1: case 2:
  383.     hsize = hpixels = 320;
  384.     correct_aspect = 0;
  385.     break;
  386.      case 3:
  387.     hsize = hpixels = 640;
  388.     break;
  389.      case 4:
  390.     hpixels = 796; hsize = 800; /* ??? */
  391.     break;
  392.     }
  393.     vsize = correct_aspect ? 2*numscrlines : numscrlines;
  394.  
  395.     cmap = XCreateColormap(display, rootwin, vis, AllocNone);
  396.     XParseColor(display, cmap, "#000000", &black);
  397.     if (!XAllocColor(display, cmap, &black))
  398.     fprintf(stderr, "Whoops??\n");
  399.     XParseColor(display, cmap, "#ffffff", &white);
  400.     if (!XAllocColor(display, cmap, &white))
  401.     fprintf(stderr, "Whoops??\n");
  402.  
  403.     wattr.event_mask = eventmask;
  404.     wattr.background_pixel = black.pixel;
  405.     wattr.backing_store = Always;
  406.     wattr.backing_planes = bitdepth;
  407.     wattr.border_pixmap = None;
  408.     wattr.border_pixel = black.pixel;
  409.     wattr.colormap = cmap;
  410.  
  411.     mywin = XCreateWindow(display, rootwin, 0, 0, hpixels, vsize, 0,
  412.               bitdepth, InputOutput, vis,
  413.               CWEventMask|CWBackPixel|CWBorderPixel|CWBackingStore
  414.               |CWBackingPlanes|CWColormap,
  415.               &wattr);
  416.     XMapWindow(display,mywin);
  417.     XStoreName(display, mywin, "UAE");
  418.     
  419.     blankCursor = XCreatePixmapCursor(display,
  420.                       XCreatePixmap(display, mywin, 1, 1, 1),
  421.                       XCreatePixmap(display, mywin, 1, 1, 1), 
  422.                       &black, &white, 0, 0);
  423.     xhairCursor = XCreateFontCursor(display, XC_crosshair);
  424.  
  425.     whitegc = XCreateGC(display,mywin,0,0);
  426.     blackgc = XCreateGC(display,mywin,0,0);
  427.     
  428.     XSetForeground(display,blackgc,black.pixel);
  429.     XSetForeground(display,whitegc,white.pixel);
  430.  
  431.     if (bitdepth < 8 || (bitdepth == 8 && color_mode == 3)) {
  432.     gfxvidinfo.pixbytes = 2;
  433.     use_low_bandwidth = 1;
  434.     need_dither = 1;
  435. #ifndef DONT_WANT_SHM
  436.     use_shm = 0;
  437. #endif
  438.     } else {
  439.     gfxvidinfo.pixbytes = (bitdepth == 24 || bitdepth == 32 ? 4
  440.                    : bitdepth == 12 || bitdepth == 16 ? 2
  441.                    : 1);
  442.     }
  443.     
  444. #ifndef DONT_WANT_SHM
  445.     if (use_shm) {
  446.     img = XShmCreateImage(display, vis, bitdepth, ZPixmap, 0, &shminfo, hsize, vsize);
  447.     
  448.     shminfo.shmid = shmget(IPC_PRIVATE, vsize * img->bytes_per_line,
  449.                    IPC_CREAT | 0777);
  450.     shminfo.shmaddr = img->data = image_mem = (char *)shmat(shminfo.shmid, 0, 0);
  451.     shminfo.readOnly = False;
  452.     /* let the xserver attach */
  453.     XShmAttach(display, &shminfo);
  454.     XSync(display,0);
  455.     /* now deleting means making it temporary */
  456.     shmctl(shminfo.shmid, IPC_RMID, 0);
  457.     } else
  458. #endif
  459.     {
  460.     /* Question for people who know about X: Could we allocate the buffer
  461.      * after creating the image and then do img->data = buffer, as above in 
  462.      * the SHM case?
  463.      */
  464.     image_mem = (char *)malloc(vsize * hsize * bit_unit / 8); /* ??? */
  465.     img = XCreateImage(display, vis, bitdepth, ZPixmap, 0, image_mem,
  466.                hsize, vsize, 32, 0);
  467.     if (img->bytes_per_line != hsize * bit_unit / 8)
  468.         fprintf (stderr, "Possible bug here... graphics may look strange.\n");
  469.     }
  470.     
  471.     if (need_dither) {
  472.     gfxvidinfo.rowbytes = gfxvidinfo.pixbytes * hsize;
  473.     gfxvidinfo.bufmem = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  474.     } else {
  475.     gfxvidinfo.rowbytes = img->bytes_per_line;
  476.     gfxvidinfo.bufmem = image_mem;
  477.     }
  478.     
  479.     gfxvidinfo.maxline = 100000; /* no limit */
  480.  
  481.     if (use_low_bandwidth) {
  482.     gfxvidinfo.maxblocklines = 0;
  483.     oldpixbuf = (char *)malloc(gfxvidinfo.rowbytes * vsize);
  484.     } else {
  485.     gfxvidinfo.maxblocklines = 100; /* whatever... */
  486.     }
  487.  
  488.     if (!init_colors())
  489.     return 0;
  490.  
  491.     buttonstate[0] = buttonstate[1] = buttonstate[2] = 0;
  492.     for(i=0; i<256; i++)
  493.     keystate[i] = 0;
  494.     
  495.     lastmx = lastmy = 0; 
  496.     newmousecounters = 0;
  497.     inwindow = 0;
  498.     
  499.     if (!no_xhair)
  500.     XDefineCursor(display, mywin, xhairCursor);
  501.     else
  502.     XDefineCursor(display, mywin, blankCursor);
  503.     cursorOn = 1;
  504.     return 1;
  505. }
  506.  
  507. void graphics_leave(void)
  508. {
  509.     if (autorepeatoff)
  510.     XAutoRepeatOn(display);
  511. }
  512.  
  513. /* Decode KeySyms. This function knows about all keys that are common 
  514.  * between different keyboard languages. */
  515. static int kc_decode (KeySym ks)
  516. {
  517.     switch (ks) {    
  518.      case XK_B: case XK_b: return AK_B;
  519.      case XK_C: case XK_c: return AK_C;
  520.      case XK_D: case XK_d: return AK_D;
  521.      case XK_E: case XK_e: return AK_E;
  522.      case XK_F: case XK_f: return AK_F;
  523.      case XK_G: case XK_g: return AK_G;
  524.      case XK_H: case XK_h: return AK_H;
  525.      case XK_I: case XK_i: return AK_I;
  526.      case XK_J: case XK_j: return AK_J;
  527.      case XK_K: case XK_k: return AK_K;
  528.      case XK_L: case XK_l: return AK_L;
  529.      case XK_N: case XK_n: return AK_N;
  530.      case XK_O: case XK_o: return AK_O;
  531.      case XK_P: case XK_p: return AK_P;
  532.      case XK_R: case XK_r: return AK_R;
  533.      case XK_S: case XK_s: return AK_S;
  534.      case XK_T: case XK_t: return AK_T;
  535.      case XK_U: case XK_u: return AK_U;
  536.      case XK_V: case XK_v: return AK_V;
  537.      case XK_W: case XK_w: return AK_W;
  538.      case XK_X: case XK_x: return AK_X;
  539.     
  540.      case XK_0: return AK_0;
  541.      case XK_1: return AK_1;
  542.      case XK_2: return AK_2;
  543.      case XK_3: return AK_3;
  544.      case XK_4: return AK_4;
  545.      case XK_5: return AK_5;
  546.      case XK_6: return AK_6;
  547.      case XK_7: return AK_7;
  548.      case XK_8: return AK_8;
  549.      case XK_9: return AK_9;
  550.     
  551.     /* You never know which Keysyms might be missing on some workstation
  552.      * This #ifdef should be enough. */
  553. #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
  554.      case XK_KP_0: case XK_KP_Insert: return AK_NP0;
  555.      case XK_KP_1: case XK_KP_End: return AK_NP1;
  556.      case XK_KP_2: case XK_KP_Down: return AK_NP2;
  557.      case XK_KP_3: case XK_KP_Next: return AK_NP3;
  558.      case XK_KP_4: case XK_KP_Left: return AK_NP4;
  559.      case XK_KP_5: case XK_KP_Begin: return AK_NP5;
  560.      case XK_KP_6: case XK_KP_Right: return AK_NP6;
  561.      case XK_KP_7: case XK_KP_Home: return AK_NP7;
  562.      case XK_KP_8: case XK_KP_Up: return AK_NP8;
  563.      case XK_KP_9: case XK_KP_Prior: return AK_NP9;
  564. #else
  565.      case XK_KP_0: return AK_NP0;
  566.      case XK_KP_1: return AK_NP1;
  567.      case XK_KP_2: return AK_NP2;
  568.      case XK_KP_3: return AK_NP3;
  569.      case XK_KP_4: return AK_NP4;
  570.      case XK_KP_5: return AK_NP5;
  571.      case XK_KP_6: return AK_NP6;
  572.      case XK_KP_7: return AK_NP7;
  573.      case XK_KP_8: return AK_NP8;
  574.      case XK_KP_9: return AK_NP9;
  575. #endif
  576.      case XK_KP_Divide: return AK_NPDIV;
  577.      case XK_KP_Multiply: return AK_NPMUL;
  578.      case XK_KP_Subtract: return AK_NPSUB;
  579.      case XK_KP_Add: return AK_NPADD;
  580.      case XK_KP_Decimal: return AK_NPDEL;
  581.      case XK_KP_Enter: return AK_ENT;
  582.  
  583.      case XK_F1: return AK_F1;
  584.      case XK_F2: return AK_F2;
  585.      case XK_F3: return AK_F3;
  586.      case XK_F4: return AK_F4;
  587.      case XK_F5: return AK_F5;
  588.      case XK_F6: return AK_F6;
  589.      case XK_F7: return AK_F7;
  590.      case XK_F8: return AK_F8;
  591.      case XK_F9: return AK_F9;
  592.      case XK_F10: return AK_F10;
  593.         
  594.      case XK_BackSpace: return AK_BS;
  595.      case XK_Delete: return AK_DEL;
  596.      case XK_Control_L: case XK_Control_R: return AK_CTRL;
  597.      case XK_Tab: return AK_TAB;
  598.      case XK_Alt_L: return AK_LALT;
  599.      case XK_Alt_R: return AK_RALT;
  600.      case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
  601.      case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
  602.      case XK_Return: return AK_RET;
  603.      case XK_space: return AK_SPC;
  604.      case XK_Shift_L: return AK_LSH;
  605.      case XK_Shift_R: return AK_RSH;
  606.      case XK_Escape: return AK_ESC;
  607.  
  608.      case XK_Insert: return AK_BACKSLASH;
  609.      case XK_End: return AK_HELP;
  610.      case XK_Caps_Lock: return AK_CAPSLOCK;
  611.     
  612.      case XK_Up: return AK_UP;
  613.      case XK_Down: return AK_DN;
  614.      case XK_Left: return AK_LF;
  615.      case XK_Right: return AK_RT;
  616.     
  617.      case XK_F11: return AK_BACKSLASH;
  618.      case XK_F12: return AK_mousestuff;
  619. #ifdef XK_F14
  620.      case XK_F14:
  621. #endif
  622.      case XK_Scroll_Lock: return AK_inhibit;
  623.  
  624. #ifdef XK_Page_Up /* These are missing occasionally */
  625.      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
  626.      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
  627. #endif
  628.     }
  629.     return -1;
  630. }
  631.  
  632. static int decode_fr(KeySym ks)
  633. {
  634.     switch(ks) {        /* FR specific */
  635.      case XK_A: case XK_a: return AK_Q;
  636.      case XK_M: case XK_m: return AK_SEMICOLON; 
  637.      case XK_Q: case XK_q: return AK_A;    
  638.      case XK_Y: case XK_y: return AK_Y;
  639.      case XK_Z: case XK_z: return AK_Z;
  640.      case XK_bracketleft: return AK_LBRACKET;
  641.      case XK_bracketright: return AK_RBRACKET;
  642.      case XK_comma: return AK_M;
  643.      case XK_less: case XK_greater: return AK_LTGT;
  644.      case XK_period: return AK_COMMA;
  645.      case XK_parenright: return AK_MINUS;
  646.      case XK_equal: return AK_SLASH;
  647.      case XK_numbersign: return AK_NUMBERSIGN;
  648.      case XK_slash: return AK_PERIOD;
  649.      case XK_minus: return AK_EQUAL;
  650.      case XK_backslash: return AK_BACKSLASH;
  651.     }
  652.  
  653.     return -1;
  654. }
  655.  
  656. static int decode_us(KeySym ks)
  657. {
  658.     switch(ks) {    /* US specific */    
  659.      case XK_A: case XK_a: return AK_A;
  660.      case XK_M: case XK_m: return AK_M;
  661.      case XK_Q: case XK_q: return AK_Q;
  662.      case XK_Y: case XK_y: return AK_Y;
  663.      case XK_Z: case XK_z: return AK_Z;
  664.      case XK_bracketleft: return AK_LBRACKET;
  665.      case XK_bracketright: return AK_RBRACKET;
  666.      case XK_comma: return AK_COMMA;
  667.      case XK_period: return AK_PERIOD;
  668.      case XK_slash: return AK_SLASH;
  669.      case XK_semicolon: return AK_SEMICOLON;
  670.      case XK_minus: return AK_MINUS;
  671.      case XK_equal: return AK_EQUAL;
  672.     /* this doesn't work: */
  673.      case XK_quoteright: return AK_QUOTE;
  674.      case XK_quoteleft: return AK_BACKQUOTE;
  675.      case XK_backslash: return AK_BACKSLASH;
  676.     }
  677.  
  678.     return -1;
  679. }
  680.  
  681. static int decode_de(KeySym ks)
  682. {
  683.     switch(ks) {
  684.     /* DE specific */
  685.      case XK_A: case XK_a: return AK_A;
  686.      case XK_M: case XK_m: return AK_M;
  687.      case XK_Q: case XK_q: return AK_Q;
  688.      case XK_Y: case XK_y: return AK_Z;
  689.      case XK_Z: case XK_z: return AK_Y;
  690.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  691.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  692.      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
  693.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  694.      case XK_comma: return AK_COMMA;
  695.      case XK_period: return AK_PERIOD;
  696.      case XK_less: case XK_greater: return AK_LTGT;
  697.      case XK_numbersign: return AK_NUMBERSIGN;
  698.      case XK_ssharp: return AK_MINUS;
  699.      case XK_apostrophe: return AK_EQUAL;
  700.      case XK_asciicircum: return AK_BACKQUOTE;
  701.      case XK_minus: return AK_SLASH;
  702.     }
  703.  
  704.     return -1;
  705. }
  706.  
  707. static int decode_se(KeySym ks)
  708. {
  709.     switch(ks) {
  710.     /* SE specific */
  711.      case XK_A: case XK_a: return AK_A;
  712.      case XK_M: case XK_m: return AK_M;
  713.      case XK_Q: case XK_q: return AK_Q;
  714.      case XK_Y: case XK_y: return AK_Y;
  715.      case XK_Z: case XK_z: return AK_Z;
  716.      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
  717.      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
  718.      case XK_Aring: case XK_aring: return AK_LBRACKET;
  719.      case XK_comma: return AK_COMMA;
  720.      case XK_period: return AK_PERIOD;
  721.      case XK_minus: return AK_SLASH;
  722.      case XK_less: case XK_greater: return AK_LTGT;
  723.      case XK_plus: case XK_question: return AK_EQUAL;
  724.      case XK_at: case XK_onehalf: return AK_BACKQUOTE;
  725.      case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
  726.      case XK_backslash: case XK_bar: return AK_MINUS;
  727.     
  728.      case XK_numbersign: return AK_NUMBERSIGN;
  729.     }
  730.  
  731.     return -1;
  732.  }
  733.  
  734. static int decode_it(KeySym ks)
  735. {
  736.     switch(ks) {
  737.     /* IT specific */
  738.      case XK_A: case XK_a: return AK_A;
  739.      case XK_M: case XK_m: return AK_M;
  740.      case XK_Q: case XK_q: return AK_Q;
  741.      case XK_Y: case XK_y: return AK_Y;
  742.      case XK_Z: case XK_z: return AK_Z;
  743.      case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
  744.      case XK_Agrave: case XK_agrave: return AK_QUOTE;
  745.      case XK_Egrave: case XK_egrave: return AK_LBRACKET;
  746.      case XK_plus: case XK_asterisk: return AK_RBRACKET;
  747.      case XK_comma: return AK_COMMA;
  748.      case XK_period: return AK_PERIOD;
  749.      case XK_less: case XK_greater: return AK_LTGT;
  750.      case XK_backslash: case XK_bar: return AK_BACKQUOTE;               
  751.      case XK_apostrophe: return AK_MINUS;           
  752.      case XK_Igrave: case XK_igrave: return AK_EQUAL;
  753.      case XK_minus: return AK_SLASH;
  754.      case XK_numbersign: return AK_NUMBERSIGN;
  755.     }
  756.  
  757.     return -1;
  758. }
  759.  
  760. static int keycode2amiga(XKeyEvent *event)
  761. {
  762.     KeySym ks;
  763.     int as;
  764.     int index = 0;
  765.     
  766.     do {
  767.     ks = XLookupKeysym(event, index);
  768.     as = kc_decode (ks);
  769.     
  770.     if (as == -1) {        
  771.         switch(keyboard_lang) {
  772.  
  773.         case KBD_LANG_FR:
  774.         as = decode_fr(ks);
  775.         break;
  776.  
  777.          case KBD_LANG_US:
  778.         as = decode_us(ks);
  779.         break;
  780.         
  781.          case KBD_LANG_DE:
  782.         as = decode_de(ks);
  783.         break;
  784.         
  785.          case KBD_LANG_SE:
  786.         as = decode_se(ks);
  787.         break;
  788.         
  789.          case KBD_LANG_IT:
  790.         as = decode_it(ks);
  791.         break;
  792.  
  793.          default:
  794.         as = -1;
  795.         break;
  796.         }
  797.     }
  798.     if(-1 != as)
  799.         return as;
  800.     index++;
  801.     } while (ks != NoSymbol);
  802.     return -1;
  803. }
  804.  
  805. static struct timeval lastMotionTime;
  806.  
  807. void handle_events(void)
  808. {
  809.     int refresh = 0;
  810.     newmousecounters = 0;
  811.     gui_handle_events();
  812.     
  813.     for (;;) {
  814.     XEvent event;
  815. #if 0
  816.     if (!XCheckMaskEvent(display, eventmask, &event)) break;
  817. #endif
  818.     if (!XPending(display)) break;
  819.     XNextEvent(display, &event);
  820.     
  821.     switch(event.type) {
  822.      case KeyPress: {        
  823.          int kc = keycode2amiga((XKeyEvent *)&event);
  824.          if (kc == -1) break;
  825.          switch (kc) {
  826.           case AK_mousestuff:
  827.          togglemouse();
  828.          break;
  829.  
  830.           case AK_inhibit:
  831.          inhibit_frame ^= 1;
  832.          break;
  833.  
  834.           default:
  835.               if (!keystate[kc]) {
  836.              keystate[kc] = 1;
  837.              record_key (kc << 1);
  838.          }
  839.          break;
  840.          }
  841.          break;
  842.      }
  843.      case KeyRelease: {         
  844.          int kc = keycode2amiga((XKeyEvent *)&event);
  845.          if (kc == -1) break;
  846.          keystate[kc] = 0;
  847.          record_key ((kc << 1) | 1);
  848.          break;
  849.      }
  850.      case ButtonPress:
  851.         buttonstate[((XButtonEvent *)&event)->button-1] = 1;
  852.         break;
  853.      case ButtonRelease:
  854.         buttonstate[((XButtonEvent *)&event)->button-1] = 0;
  855.         break;
  856.      case EnterNotify:
  857.         newmousecounters = 1;
  858.         lastmx = ((XCrossingEvent *)&event)->x;
  859.         lastmy = ((XCrossingEvent *)&event)->y;
  860.         inwindow = 1;
  861.         break;
  862.      case LeaveNotify:
  863.         inwindow = 0;
  864.         break;
  865.      case FocusIn:
  866.         if (!autorepeatoff)
  867.         XAutoRepeatOff(display);
  868.         autorepeatoff = 1;
  869.         break;
  870.      case FocusOut:
  871.         if (autorepeatoff)
  872.         XAutoRepeatOn(display);
  873.         autorepeatoff = 0;
  874.         break;
  875.      case MotionNotify:
  876.         if (inwindow) {        
  877.         lastmx = ((XMotionEvent *)&event)->x;
  878.         lastmy = ((XMotionEvent *)&event)->y;
  879.         if(!cursorOn && !no_xhair) {
  880.             XDefineCursor(display, mywin, xhairCursor);
  881.             cursorOn = 1;
  882.         }
  883.         gettimeofday(&lastMotionTime, NULL);
  884.         }
  885.         break;
  886.      case Expose:
  887.         refresh = 1;
  888.         break;
  889.     }
  890.     }
  891.  
  892.     if(refresh) {
  893. #ifndef DONT_WANT_SHM
  894.     if (use_shm)
  895.         XShmPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize, 0);
  896.     else
  897. #endif
  898.         XPutImage(display, mywin, blackgc, img, 0, 0, 0, 0, hpixels, vsize);
  899.     }
  900.     if(cursorOn && !no_xhair) {
  901.     struct timeval now;
  902.     int diff;
  903.     gettimeofday(&now, NULL);
  904.     diff = (now.tv_sec - lastMotionTime.tv_sec) * 1000000 + 
  905.         (now.tv_usec - lastMotionTime.tv_usec);
  906.     if(diff > 1000000) {
  907.         XDefineCursor(display, mywin, blankCursor);
  908.         cursorOn = 0;
  909.     }
  910.     }
  911.     
  912.     /* "Affengriff" */
  913.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
  914.         m68k_reset();
  915. }
  916.  
  917. int debuggable(void)
  918. {
  919.     return 1;
  920. }
  921.  
  922. int needmousehack(void)
  923. {
  924.     return 1;
  925. }
  926.  
  927. void LED(int on)
  928. {
  929.     static int last_on = -1;
  930.     XKeyboardControl control;
  931.  
  932.     if (last_on == on) return;
  933.     last_on = on;
  934.     control.led = 1; /* implementation defined */
  935.     control.led_mode = on ? LedModeOn : LedModeOff;
  936.     XChangeKeyboardControl(display, KBLed | KBLedMode, &control);
  937. }
  938.  
  939. void target_specific_usage(void)
  940. {
  941.     printf("  -S n                     : Sound emulation accuracy (n = 0, 1, 2 or 3)\n"
  942.        "                             For sound emulation, n = 2 is recommended\n");
  943.     printf("  -b n                     : Use n bits for sound output (8 or 16)\n");
  944.     printf("  -R n                     : Use n Hz to output sound. Common values are\n"
  945.        "                             22050 Hz or 44100 Hz\n");
  946.     printf("  -B n                     : Use a sound buffer of n bytes (use small\n"
  947.        "                             values on fast machines)\n");
  948.     printf("  -x                       : Use visible cross-hair cursor\n");
  949.     printf("  -l lang                  : Set keyboard language to lang, where lang is\n"
  950.        "                             DE, SE, US, FR or IT\n");
  951.     printf("  -p command               : Use command to pipe printer output to.\n");
  952.     printf("  -I device                : Name of the used serial device (i.e. /dev/ttyS1\n");
  953. }
  954.